package com.wx.sys.shiro;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.util.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.wx.base.util.jedis.JedisManager;
import com.wx.base.util.jedis.SerializeUtils;

public class JedisCache<K, V> implements Cache<K, V> {
	private static final Logger logger = LoggerFactory.getLogger(JedisCache.class);
	private JedisManager cache;
	private String keyPrefix = "shiro_redis_session:";

	public JedisCache(JedisManager cache) {
		if(cache==null){
			throw new IllegalArgumentException("Cache argument cannot be null.");
		}
		this.cache = cache;
	}

	public JedisCache(JedisManager cache, String keyPrefix) {
		this(cache);
		this.keyPrefix = keyPrefix;
	}
	private byte[] getByteKey(K key){
		if(key instanceof String){
			String preKey = this.keyPrefix+key;
			return preKey.getBytes();
		}else {
			return SerializeUtils.serialize(key);
		}
	}

	public V get(K key) throws CacheException {
		logger.debug("根据key从Redis中获取对象 key [" + key + "]");
		if(key==null){
			return null;
		}else {
			byte[]rawValue = cache.get(getByteKey(key));
			V value = (V) SerializeUtils.deserialize(rawValue);
			return value;
		}
	}

	public V put(K key, V value) throws CacheException {
		logger.debug("根据key从redis存入对象key["+key+"]");
		cache.set(getByteKey(key), SerializeUtils.serialize(value));
		return value;
	}

	public V remove(K key) throws CacheException {
		logger.debug("根据key从redis删除对象key["+key+"]");
		cache.del(getByteKey(key));
		return get(key);
	}

	public void clear() throws CacheException {
		logger.debug("删除所有数据");
		cache.flushDB();
	}

	public int size() {
		return cache.dbSize().intValue();
	}

	public Set<K> keys() {
		try {
            Set<byte[]> keys = cache.keys(this.keyPrefix + "*");
            if (CollectionUtils.isEmpty(keys)) {
            	return Collections.emptySet();
            }else{
            	Set<K> newKeys = new HashSet<K>();
            	for(byte[] key:keys){
            		newKeys.add((K)key);
            	}
            	return newKeys;
            }
        } catch (Throwable t) {
            throw new CacheException(t);
        }
	}

	public Collection<V> values() {
		try {
            Set<byte[]> keys = cache.keys(this.keyPrefix + "*");
            if (!CollectionUtils.isEmpty(keys)) {
                List<V> values = new ArrayList<V>(keys.size());
                for (byte[] key : keys) {
                    @SuppressWarnings("unchecked")
					V value = get((K)key);
                    if (value != null) {
                        values.add(value);
                    }
                }
                return Collections.unmodifiableList(values);
            } else {
                return Collections.emptyList();
            }
        } catch (Throwable t) {
            throw new CacheException(t);
        }
	}

}
